import re
import json
import time
import pynput
import pywinctl
import subprocess
from typing import Callable, Optional
from .typer import TypeWriter

@lambda x: setattr(__import__('ewmhlib').EwmhWindow, 'getName', x)
def ewmhFixedGetName(self) -> Optional[str]:
    from ewmhlib.Props._props import Window
    from ewmhlib import getPropertyValue
    ret = self.getProperty(Window.NAME)
    res = getPropertyValue(ret, display=self.display)
    if res:
        return ''.join(map(str, res))
    ret = self.getProperty(Window.LEGACY_NAME)
    res = getPropertyValue(ret, display=self.display)
    if res:
        return ''.join(map(str, res))
    return None

class AppWriter(TypeWriter):
    def __init__(self, title: str | None = None, program: str | list[str] | None = None, shortcut: str | None = None, enter: bool = False, click: bool = False, lookup: Callable[[str], str] | dict | str | None = None):
        super().__init__()
        self.title = title
        program = program
        if isinstance(program, str):
            program = [program]
        self.program = program
        self.shortcut = shortcut
        self.enter = enter
        self.click = click
        if isinstance(lookup, str):
            lookup_s = lookup
            lookup = {}
            for line in lookup_s.splitlines():
                line = line.strip()
                if not line:
                    continue
                line = line.split('=', maxsplit=1)
                if len(line) != 2:
                    continue
                term, actual = line
                if len(actual) >= 2 and actual.startswith('"') and actual.endswith('"'):
                    actual = json.loads(actual)
                for t in term.split(','):
                    lookup[t] = actual
        if isinstance(lookup, dict):
            lookup = {k.lower(): v for k, v in lookup.items()}
            self.lookup = lambda t: lookup.get(t.lower(), t)
        else:
            self.lookup = lookup

    def goto_or_start(self):
        if not self.title:
            return True
        active_win = pywinctl.getActiveWindow()
        if active_win and re.search(self.title, active_win.title):
            return True
        for win in pywinctl.getAllWindows():
            if re.search(self.title, win.title):
                win.activate(True)
                return True
        if self.program:
            subprocess.Popen(self.program, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
            duration = 0.06
            for _ in range(5):
                for win in pywinctl.getAllWindows():
                    if re.search(self.title, win.title):
                        win.activate(True)
                        return True
                time.sleep(duration)
                duration *= 1.75
        return False

    def do_start(self):
        if self.goto_or_start():
            if self.shortcut:
                for cut in self.shortcut.split(' '):
                    if not cut:
                        continue
                    cut = cut.lower().split('+')
                    for c in cut:
                        self.keyboard.press(getattr(pynput.keyboard.Key, c, c))
                    time.sleep(0.01)
                    for c in reversed(cut):
                        self.keyboard.release(getattr(pynput.keyboard.Key, c, c))
        super().do_start()

    def do_input(self, text):
        if self.lookup:
            text = self.lookup(text)
        super().do_input(text)

    def do_finish(self):
        super().do_finish(enter=self.enter)

if __name__ == '__main__':
    writer = AppWriter(r'- Mousepad$', program='mousepad')
    writer.input('print("你好，世界！")', True)
